/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package game;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import other.Costants;

/**
 *
 * @author alessandro
 */
public class Deck implements Serializable {

    private final int N_CARDS = 52;
    private List<Card> cards = new ArrayList<Card>(0);
    private ArrayList<Card> cardsPlayer1 = new ArrayList<Card>(13);
    private ArrayList<Card> cardsPlayer2 = new ArrayList<Card>(13);
    private ArrayList<Card> cardsPlayer3 = new ArrayList<Card>(13);
    private ArrayList<Card> cardsPlayer4 = new ArrayList<Card>(13);
    private int token;
    private String firstSeed;
    private boolean heartsBroken;
    private int round;

    public Deck() {
        this.createDeck();
        this.token = Costants.NULL;
    }

    /* GETTERS AND SETTERS */

    
    public List<Card> getCards() {
        return cards;
    }

    public String getFirstSeed() {
        return firstSeed;
    }

    public void setFirstSeed(String firstSeed) {
        this.firstSeed = firstSeed;
    }

    public boolean isHeartsBroken() {
        return heartsBroken;
    }

    public void setHeartsBroken(boolean heartsBroken) {
        this.heartsBroken = heartsBroken;
    }

    public int getRound() {
        return round;
    }

    public void setRound(int round) {
        this.round = round;
    }

    public void setCards(List<Card> cards) {
        this.cards = cards;
    }

    public ArrayList<Card> getCardsPlayer1() {
        return cardsPlayer1;
    }

    public void setCardsPlayer1(ArrayList<Card> cardsPlayer1) {
        this.cardsPlayer1 = cardsPlayer1;
    }

    public ArrayList<Card> getCardsPlayer2() {
        return cardsPlayer2;
    }

    public void setCardsPlayer2(ArrayList<Card> cardsPlayer2) {
        this.cardsPlayer2 = cardsPlayer2;
    }

    public ArrayList<Card> getCardsPlayer3() {
        return cardsPlayer3;
    }

    public void setCardsPlayer3(ArrayList<Card> cardsPlayer3) {
        this.cardsPlayer3 = cardsPlayer3;
    }

    public ArrayList<Card> getCardsPlayer4() {
        return cardsPlayer4;
    }

    public void setCardsPlayer4(ArrayList<Card> cardsPlayer4) {
        this.cardsPlayer4 = cardsPlayer4;
    }

    public int getToken() {
        return token;
    }

    public void setToken(int token) {
        if (token >= 4) {
            token = 0;
        }
        this.token = token;
    }

    /* METODI */
    /* crea il mazzo di carte */
    private void createDeck() {
        /*prende le 52 carte e le mette in lista*/
        for (int j = 0; j < Costants.SEED.length; j++) {
            for (int x = 0; x < Costants.CARDS.length; x++) {
                if (!(Costants.CARDS[x] == 2 && Costants.SEED[j].equals("F"))) { //il 2 di fiori non viene inserito nel mazzo
                    Card card = new Card(Costants.SEED[j], Costants.CARDS[x]);
                    card.setState(Costants.HOLD_BY_USER);
                    cards.add(card);
                }
            }
        }

        //System.out.println("MAZZO DA " + cards.size());

    }

    public ArrayList<Card> sortPlayerCard(ArrayList playerCards) {
        Collections.sort(playerCards);
        return playerCards;
    }

    /* da le carte a tutti i giocatori, partendo dal 2 di fiori */
    public void startGivingCards() {
        token = (int) (3 * Math.random());
        round = 0;
        //System.out.println("TOKEN:" + token);
        int NORMAL = 13;
        int START = 0;
        int END = 13;
        Card dueFiori = new Card("F", 2); //2 di fiori
        firstSeed = Costants.SEED_F;

        //algoritmo per assegnare il 2 di fiori
        if (token == 0) {
            cardsPlayer1.add(dueFiori);
            END = END - 1;
        }
        cardsPlayer1.addAll(cards.subList(START, END));
        //System.out.println("Giocatore 1 n. carte:" + cardsPlayer1.size());
        //System.out.println("Prima carta giocatore 1:" + cardsPlayer1.get(0).getSeed() + cardsPlayer1.get(0).getNumber());
        //System.out.println("Ultima carta giocatore 1:" + cardsPlayer1.get(cardsPlayer1.size() - 1).getSeed() + cardsPlayer1.get(cardsPlayer1.size() - 1).getNumber());

        START = END;
        END = END + NORMAL;

        if (token == 1) {
            cardsPlayer2.add(dueFiori);
            END = END - 1;
        }
        cardsPlayer2.addAll(cards.subList(START, END));
        //System.out.println("Giocatore 2 n. carte:" + cardsPlayer2.size());
        //System.out.println("Prima carta giocatore 2:" + cardsPlayer2.get(0).getSeed() + cardsPlayer2.get(0).getNumber());
        //System.out.println("Ultima carta giocatore 2:" + cardsPlayer2.get(cardsPlayer2.size() - 1).getSeed() + cardsPlayer2.get(cardsPlayer2.size() - 1).getNumber());

        START = END;
        END = END + NORMAL;

        if (token == 2) {
            cardsPlayer3.add(dueFiori);
            END = END - 1;
        }
        cardsPlayer3.addAll(cards.subList(START, END));
        //System.out.println("Giocatore 3 n. carte:" + cardsPlayer3.size());
        //System.out.println("Prima carta giocatore 3:" + cardsPlayer3.get(0).getSeed() + cardsPlayer3.get(0).getNumber());
        //System.out.println("Ultima carta giocatore 3:" + cardsPlayer3.get(cardsPlayer3.size() - 1).getSeed() + cardsPlayer3.get(cardsPlayer3.size() - 1).getNumber());

        START = END;
        END = START + NORMAL;

        if (token == 3) {
            cardsPlayer4.add(dueFiori);
            END = END - 1;
        }
        cardsPlayer4.addAll(cards.subList(START, END));
        //System.out.println("Giocatore 4 n. carte:" + cardsPlayer4.size());
        //System.out.println("Prima carta giocatore 4:" + cardsPlayer4.get(0).getSeed() + cardsPlayer4.get(0).getNumber());
        //System.out.println("Ultima carta giocatore 4:" + cardsPlayer4.get(cardsPlayer4.size() - 1).getSeed() + cardsPlayer4.get(cardsPlayer4.size() - 1).getNumber());

        START = 0;
        END = 13;

        cardsPlayer1 = this.sortPlayerCard(cardsPlayer1);
        cardsPlayer2 = this.sortPlayerCard(cardsPlayer2);
        cardsPlayer3 = this.sortPlayerCard(cardsPlayer3);
        cardsPlayer4 = this.sortPlayerCard(cardsPlayer4);

    }

    /* ritorna il numero di carte del giocatore in base allo status della carta*/
    public int getCardsNumberStatus(ArrayList<Card> cards, String statusCards) {
        int number = 0;
        try {
            number = this.getCardsFromStatus(cards, statusCards).size();
        } catch (Exception e) {
            System.out.println("Errore in getCardsNumberStatus");
        }
        return number;
    }

    /* ritorna quante carte ha il giocatore con quel seme */
    public int getNumberCardsFromSeed(ArrayList<Card> cards, String statusCards, String seed) {
        int number = 0;

        ArrayList<Card> cardsP = this.getCardsFromStatus(cards, statusCards);
        if (!(cardsP.isEmpty())) {

            for (int i = 0; i < cardsP.size(); i++) {
                if (cardsP.get(i).getSeed().equals(seed)) {
                    number++;
                }
            }
        }

        return number;
    }

    public ArrayList<Card> getCardsFromStatus(ArrayList<Card> cards, String statusCards) {
        ArrayList<Card> cardsT = new ArrayList<Card>();
        for (int i = 0; i < cards.size(); i++) {
            if (cards.get(i).getState().equals(statusCards)) {
                try {
                    cardsT.add(cards.get(i));
                } catch (Exception e) {
                    System.out.println("Errore in getCardsFromStatus");
                }
            }
        }
        return cardsT;

    }

    public int getFirstCardsIndexFromStatus(ArrayList<Card> cards, String statusCards) {
        for (int i = 0; i < cards.size(); i++) {
            if (cards.get(i).getState().equals(statusCards)) {
                return i;
            }
        }
        return -1;

    }

    /* mischia il mazzo di carte */
    public void shuffleCards() {
        Collections.shuffle(cards);
    }

    /*cerca una carta in un mazzo dato in input */
    public Card searchCard(ArrayList<Card> cards, String cardString) {
        Card card = null;
        try {
            String seed = cardString.substring(0, 1); //prendo il seme
            int number = Integer.parseInt(cardString.substring(1)); //prendo il numero

            for (int i = 0; i < cards.size(); i++) {
                if (cards.get(i).getSeed().equals(seed) && cards.get(i).getNumber() == number) {
                    return cards.get(i);
                }
            }

        } catch (Exception e) {
            System.out.println("Errore in searchCard");
        }

        return card;
    }

    /* setta la carta in input come ON_TABLE */
    public void setCardPlayerOnTable(int idPlayer, String cardString) {
        Card card = null;
        switch (idPlayer) {
            case 0:
                card = this.searchCard(cardsPlayer1, cardString);
                if (card != null) {
                    cardsPlayer1.remove(card);
                    card.setState(Costants.ON_TABLE);
                    cardsPlayer1.add(card);
                }
                break;
            case 1:
                card = this.searchCard(cardsPlayer2, cardString);
                if (card != null) {
                    cardsPlayer2.remove(card);
                    card.setState(Costants.ON_TABLE);
                    cardsPlayer2.add(card);
                }
                break;
            case 2:
                card = this.searchCard(cardsPlayer3, cardString);
                if (card != null) {
                    cardsPlayer3.remove(card);
                    card.setState(Costants.ON_TABLE);
                    cardsPlayer3.add(card);
                }
                break;
            case 3:
                card = this.searchCard(cardsPlayer4, cardString);
                if (card != null) {
                    cardsPlayer4.remove(card);
                    card.setState(Costants.ON_TABLE);
                    cardsPlayer4.add(card);
                }
                break;
        }
    }

    /* lista carte sul tavolo */
    public ArrayList<Card> getTableCards() {

        ArrayList<Card> cardsOnTableT = new ArrayList<Card>();

        for (int i = 0; i < 4; i++) {
            ArrayList<Card> cardsP = new ArrayList<Card>();
            switch (i) {
                case 0:
                    cardsP = cardsPlayer1;
                    break;
                case 1:
                    cardsP = cardsPlayer2;
                    break;
                case 2:
                    cardsP = cardsPlayer3;
                    break;
                case 3:
                    cardsP = cardsPlayer4;
                    break;
            }
            for (int j = 0; j < cardsP.size(); j++) {
                if (cardsP.get(j).getState().equals(Costants.ON_TABLE)) {
                    cardsOnTableT.add(cardsP.get(j));
                    break;
                }
            }
        }
        return cardsOnTableT;
    }

    /* fa il controllo sulle 4 carte sul tavolo */
    public boolean checkFourCards() {
        ArrayList<Card> cardsOnTable = this.getTableCards();
        int size = cardsOnTable.size();
        //System.out.println(size +" carte sul tavolo!");
        if (size == 4) {
            //System.out.println("4 carte sul tavolo! WIN!");
            return true;
        } else {
            return false;
        }

    }

    /* setta le carte ON_TABLE a POINT e assegna il Token che le prende*/
    public boolean endTurn() {
        ArrayList<Card> cardsOnTable = this.getTableCards();
        boolean flag = false;
        int indexGet = Costants.NULL;
        if (cardsOnTable.size() == 4) {
            //System.out.println("CARTE SUL TAVOLO: " + cardsOnTable.size());
            Card maxCard = new Card(firstSeed, 0);
            for (int i = 0; i < cardsOnTable.size(); i++) { //prendo la carta più alta
                Card card = cardsOnTable.get(i);

                switch (i) {
                    case 0:
                        boolean index1 = cardsPlayer1.remove(card);
                        System.out.println("INDEX PLAYER1: " + index1);
                        break;
                    case 1:
                        boolean index2 = cardsPlayer2.remove(card);
                        System.out.println("INDEX PLAYER2: " + index2);
                        break;
                    case 2:
                        boolean index3  = cardsPlayer3.remove(card);
                        System.out.println("INDEX PLAYER3: " + index3);
                        break;
                    case 3:
                        boolean index4 = cardsPlayer4.remove(card);
                        System.out.println("INDEX PLAYER4: " + index4);
                        break;
                }
                card.setState(Costants.POINT);
                cardsOnTable.set(i, card);
                //System.out.println("MAXCARD: " + maxCard.getSeed() + maxCard.getNumber());
                //System.out.println("CARTA SUL TAVOLO: " + cardsOnTable.get(i).getSeed() + cardsOnTable.get(i).getNumber());
                if (cardsOnTable.get(i).getSeed().equals(firstSeed) && cardsOnTable.get(i).getNumber() > maxCard.getNumber()) {
                    maxCard = cardsOnTable.get(i);
                    indexGet = i;
                }

            }
            /*
            //System.out.println("Indice indexGet: " + indexGet);
            int index1 = this.getFirstCardsIndexFromStatus(cardsPlayer1, Costants.ON_TABLE);
            int index2 = this.getFirstCardsIndexFromStatus(cardsPlayer2, Costants.ON_TABLE);
            int index3 = this.getFirstCardsIndexFromStatus(cardsPlayer3, Costants.ON_TABLE);
            int index4 = this.getFirstCardsIndexFromStatus(cardsPlayer4, Costants.ON_TABLE);

            System.out.println("INDEX PLAYER1: " + index1);
            System.out.println("INDEX PLAYER2: " + index2);
            System.out.println("INDEX PLAYER3: " + index3);
            System.out.println("INDEX PLAYER4: " + index4);

            if (index1 >= 0) {
                cardsPlayer1.remove(index1);
            }
            if (index2 >= 0) {
                cardsPlayer2.remove(index2);
            }
            if (index3 >= 0) {
                cardsPlayer3.remove(index3);
            }
            if (index4 >= 0) {
                cardsPlayer4.remove(index4);
            }*/

            System.out.println("RIMOSSO le CARTE E AGGIUNGO LE NUOVE");

            switch (indexGet) {
                case 0:
                    cardsPlayer1.addAll(cardsOnTable);
                    break;
                case 1:
                    cardsPlayer2.addAll(cardsOnTable);
                    break;
                case 2:
                    cardsPlayer3.addAll(cardsOnTable);
                    break;
                case 3:
                    cardsPlayer4.addAll(cardsOnTable);
                    break;
            }

            flag = true;

            cardsOnTable.clear();
            this.setToken(indexGet); //setto il giocatore che inizierà il prossimo turno
            round = round + 1;
        }
        return flag;

    }

    /* assegna il vincitore */
    public ArrayList<Integer> getWinner() {
        ArrayList<Integer> winnerIndex = new ArrayList<Integer>();

        ArrayList<Integer> points = new ArrayList<Integer>();

        points.add(this.calcPoints(this.cardsPlayer1));
        points.add(this.calcPoints(this.cardsPlayer2));
        points.add(this.calcPoints(this.cardsPlayer3));
        points.add(this.calcPoints(this.cardsPlayer4));

        int minPoint = 5000;
        boolean shooting = false;
        for (int i = 0; i < points.size(); i++) {
            if (points.get(i) == Costants.POINTS_SHOOTING) { //controllo se c'è qualche player che ha fatto moon_shooting
                shooting = true;
                winnerIndex.add(i);
            } else {
                if (points.get(i) < minPoint) {
                    minPoint = points.get(i);
                }
            }
        }
        if (!shooting) { // se non c'è stato il moon_shooting
            for (int i = 0; i < points.size(); i++) {
                if (points.get(i) == minPoint) {
                    winnerIndex.add(i);
                }
            }
        }
        return  winnerIndex;
    }
    /* calcola i punteggi in base alle regole di Hearts */
    private int calcPoints(ArrayList<Card> cards) {
        int points = 0;

        for(int i = 0; i<cards.size(); i++) {
            if(cards.get(i).getSeed().equals(Costants.SEED_C)) {
                points = points + 1;
            } else if(cards.get(i).getSeed().equals(Costants.SEED_P) && cards.get(i).getNumber() == 12) {
                points = points + 13;
            }
        }
        System.out.println("PUNTI " + points);
        return points;
    }
}
